#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Predesys - Predesys LAN Radar
# Version: 0.2.2
# Author: Jose A. Jimenez <jajimc@gmail.com>
# License: GPL 3.0 (see "license" file)

import sys
sys.dont_write_bytecode = True
import os
import os.path
import commands
import time
from signal import SIGTERM
import daemon
import time
import configuration
import simplexml
import xmlrpclib
import radarexceptions
import messages

# File to save process ID
DAEMON_PID_FILE = "/tmp/predesys-lan-radar.pid"

# File to save exception messages
DAEMON_ERROR_FILE = "/tmp/predesys-lan-radar.err"

# ARP cache file
ARP_CACHE_FILE = "/proc/net/arp"

class PredesysRadar(daemon.Daemon):
    """Predesys Radar daemon.
    """
    def __init__(self):
        self.__load_configuration()
        self.clientProxy = xmlrpclib.ServerProxy(self.config.get_server_webservice_address())
            
        daemon.Daemon.__init__(self, pidfile=DAEMON_PID_FILE, stderr=DAEMON_ERROR_FILE)
            
    def __load_configuration(self):
        """Loads configuration from CONFIG_FILE_1 file or CONFIG_FILE_2 file.
        
        If an error occurs, it sets the default configuration.
        """
        self.config = configuration.load_configuration()
        self.network_interface = self.config.get_network_interface()
        
    def run(self):
        """Does the daemon work.
        """
        scanInterval = self.config.get_scan_interval()
        if scanInterval < 1: scanInterval = 1
        
        while (True):
            try:
                devices = self.__get_devices()
                if len(devices) > 0:
                    response = self.__send_devices_to_server(devices)
                    if response != None and response != "": self.__manage_response(response)
                time.sleep(scanInterval)
            except:
                # ToDo: Log errors
                pass

    def __get_devices(self):
        devices = []

        try:
            status, output = commands.getstatusoutput("arp-scan -interface=%s --localnet" % self.network_interface)
            if status != 0:
                raise Exception(output)
                
            lines = output.split("\n")

            for i in range(2, len(lines)-3):
                macAddress = lines[i].split()[1]        
                if devices.count(macAddress) == 0:
                    devices.append(macAddress)
        except:
            # ToDo: Log errors
            pass

        return devices

    def __send_devices_to_server(self, devices):
        return self.clientProxy.run_callable_authenticated_service("radar", devices, self.config.get_user_id(), self.config.get_user_password())
        
    def __manage_response(self, response):
        if messages.is_message_list_group(response):
            for messageList in messages.get_message_lists(response):
                if messages.is_message_list(messageList):
                    for message in messages.get_messages(messageList):
                        try:
                            # ToDo: Manage timeout
                            destination, body = messages.get_message_data(message)
                            self.__send_message(destination, body)
                        except:
                            # ToDo: Log errors
                            pass
        
    # ToDo
    def __send_message(self, destination, body):
        if destination == None or type(destination) != str or destination == "":
            raise radarexceptions.ValueNotValidException("Destination must be a not null and not empty string.")
        if body == None or type(body) != str or body == "":
            raise radarexceptions.ValueNotValidException("Body must be a not null and not empty string.")
        return
            
if __name__ == "__main__":
    if len(sys.argv) == 2:
        if sys.argv[1] == "start":
            PredesysRadar().start()
        elif sys.argv[1] == "restart":
            PredesysRadar().restart()
        elif sys.argv[1] == "stop":
            PredesysRadar().stop()
        else:
            print "Unknown command"
            sys.exit(2)
        sys.exit(0)
    else:
        print "Usage: %s start|stop|restart" % sys.argv[0]
        sys.exit(2)
